#include <Tone.h>
#include <MsTimer2.h>

#define N 64
#define TAP_N 8
#define SET_HIGH digitalWrite(13, 1)
#define SET_LOW digitalWrite(13, 0)
const char signal[4] = {0, 0x01, 0x02, 0x08};
char count = 2;
void light(char signal)
{
  digitalWrite(2, 0x01&signal);
  digitalWrite(3, 0x02&signal);
  digitalWrite(4, 0x08&signal);
}
void show_light()
{
  light(signal[count++]);
  if (count > 3)
    count = 0;
}

struct BUF
{
  int data[N];
  int count;
};
struct BUF tx_buf, rx_buf;

void push(struct BUF *buf, int x)
{
  if(buf->count < N)
  {
    buf->data[ buf->count ] = x;
    buf->count++;
  }
}

int pop(struct BUF *buf)
{
  if(buf->count != 0)
  {
    buf->count --;
    return buf->data[buf->count];
  }
}

void print_data(struct BUF *buf, char flag)
{
  int i;
  for (i=0; i<N; i++)
  {
       Serial.print("Debug:\t ");
       Serial.print(i);
       Serial.print("\t:\t");
       if(flag)
         Serial.print(buf->data[i], DEC);
       else
         Serial.print(buf->data[N-i-1], DEC);
       Serial.print("\n");
  }
    
}
void compare()
{
  int i,err=0;
  for (i = 0 ; i<N; i++)
  {
    if(tx_buf.data[i] != rx_buf.data[N-i-1])
      err++;
  }
  if(err)
    light(0x01);
  else
    light(0x02);
    

  Serial.print("End Comm in one second\n");
  Serial.print("Total bits = ");
  Serial.print(N);
  Serial.print("\n");
  
  Serial.print("ERROR bits = ");
  Serial.print(err);
  Serial.print("\n");
  

  Serial.print("\nTX DATA:\n");
  print_data(&tx_buf, 1);
  Serial.print("\nRX DATA:\n");
  print_data(&rx_buf, 0);

}

void filter(struct BUF *buf)
{
  long sum = 0;
  int i;
  for(i=0; i<N; i++)
  {
    sum +=  buf->data[i] / N;
  }
  Serial.println("Decesion Line: \t");
  Serial.println(sum*0.0049, 4);
  for(i=0; i<N; i++)
  {
    buf->data[i] = buf->data[i] > sum;
  }
}
int rx_2()
{
  return analogRead(A0);
}

void rx_1()
{
   if(rx_buf.count!=N)
  {
    push ( &rx_buf, rx_2() );
  }
  else
  {
      MsTimer2::stop();
      filter(&rx_buf);
      compare();
  }
}
boolean sch_flag = true;
void sche()
{
  cli();
  
  if(sch_flag)
  {
    SET_HIGH;
    tx_1();
  }
  else
  {
    SET_LOW;
    rx_1();
  }
  sch_flag = !sch_flag;
  
  sei();
}
void tx_1()
{
  if(tx_buf.count!=0)
    digitalWrite(7, pop(&tx_buf)); 
}


void tx()
{
  MsTimer2::set(5, sche); // set the transmitting freq
  MsTimer2::start();
}

boolean bits = false;
void gen_data()
{
  int i;  
  tx_buf.count = 0;
  rx_buf.count = 0;
  for (i=0; i < N ; i ++ )
    push(&tx_buf, random(2));
    //push(&tx_buf, bits=!bits); //debug using
    
}

void setup() {
  Serial.begin(9600);
  randomSeed(analogRead(A5));
  pinMode(7, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  //analogReference(INTERNAL);
  Serial.print("Start Tx in one second\n");
  delay(1000);
  gen_data();
  tx();

}



void loop() {
  ;
}


